﻿using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net.Http;
using System.Net;
using System.Text;
using System.Threading.Tasks;
using JkUtils.JKTypes;
using System.Runtime.InteropServices;
using System.Net.Http.Headers; // 新增

namespace JkUtils
{
    public class HttpResponseResult
    {
        public string Content { get; set; }
        public Dictionary<string, string> Headers { get; set; }
        public HttpStatusCode StatusCode { get; set; }
    }

    public class HttpResult<T>
    {
        public T Data { get; set; }
        public Dictionary<string, string> Headers { get; set; }
    }

    public class JKHttpUtil
    {
        public HttpClient HttpClientSettings(Dictionary<string, string> customHeaders, ProxySetting proxySetting, string url)
        {
            var handler = new HttpClientHandler() { AutomaticDecompression = DecompressionMethods.None };

            if (proxySetting != null && proxySetting.UseProxy)
            {
                string proxyUrl = string.Format("{0}://{1}:{2}", proxySetting.Protocol, proxySetting.Address, proxySetting.Port);
                IWebProxy webProxy = new WebProxy(proxyUrl);
                if (proxySetting.ProxyCredentials != null &&
                    !string.IsNullOrEmpty(proxySetting.ProxyCredentials.UserName) &&
                    !string.IsNullOrEmpty(proxySetting.ProxyCredentials.Password))
                {
                    webProxy.Credentials = new NetworkCredential(proxySetting.ProxyCredentials.UserName, proxySetting.ProxyCredentials.Password);
                }
                handler.Proxy = webProxy;
                handler.UseProxy = true;
            }

            HttpClient httpclient = new HttpClient(handler);
            httpclient.DefaultRequestHeaders.Accept.Clear();
            httpclient.DefaultRequestHeaders.Accept.Add(new System.Net.Http.Headers.MediaTypeWithQualityHeaderValue("application/json"));

            if (customHeaders != null)
            {
                foreach (KeyValuePair<string, string> headerItem in customHeaders)
                {
                    if (!string.IsNullOrEmpty(headerItem.Value))
                    {
                        httpclient.DefaultRequestHeaders.Add(headerItem.Key, headerItem.Value.Trim());
                    }
                }
            }

            HttpMode httpMode = getHttpModeByUrl(url);
            if (httpMode == HttpMode.HTTPS)
            {
                trustCertificate();
            }

            return httpclient;
        }

        private void trustCertificate()
        {
            ServicePointManager.ServerCertificateValidationCallback += (sender, cert, chain, sslPolicyErrors) => true;
            ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12 | SecurityProtocolType.Tls11 | SecurityProtocolType.Tls | SecurityProtocolType.Ssl3;
        }

        private HttpMode getHttpModeByUrl(string url)
        {
            HttpMode httpMode = HttpMode.HTTP;
            if (url.StartsWith("https", StringComparison.OrdinalIgnoreCase))
            {
                httpMode = HttpMode.HTTPS;
            }
            return httpMode;
        }

        // 原方法保持不变（内部调用新增重载，默认仍压缩）
        public HttpResponseResult HttpclientCall(string url, HttpContent paramlist, Dictionary<string, string> customHeaders, ProxySetting proxySetting, HttpMethodType httpMethodType)
        {
            return HttpclientCall(url, paramlist, customHeaders, proxySetting, httpMethodType, true);
        }

        // 新增：可选择是否压缩（文件上传需关闭）
        public HttpResponseResult HttpclientCall(string url, HttpContent paramlist, Dictionary<string, string> customHeaders, ProxySetting proxySetting, HttpMethodType httpMethodType, bool useCompression)
        {
            HttpClient httpclient = null;
            Stream ResponseStream = null;
            StreamReader sr = null;
            HttpResponseMessage response = null;
            try
            {
                httpclient = HttpClientSettings(customHeaders, proxySetting, url);
                HttpContent realContent = paramlist;
                if (paramlist != null && useCompression)
                {
                    realContent = new CompressedContent(paramlist, CompressionType.GZip);
                }

                string retString = string.Empty;

                switch (httpMethodType)
                {
                    case HttpMethodType.GET:
                        response = httpclient.GetAsync(new Uri(url)).Result;
                        break;
                    case HttpMethodType.POST:
                        response = httpclient.PostAsync(new Uri(url), realContent).Result;
                        break;
                    case HttpMethodType.PUT:
                        response = httpclient.PutAsync(new Uri(url), realContent).Result;
                        break;
                    case HttpMethodType.DELETE:
                        response = httpclient.DeleteAsync(new Uri(url)).Result;
                        break;
                    default:
                        throw new NotSupportedException("This type is not supported!");
                }
                response.EnsureSuccessStatusCode();

                ResponseStream = response.Content.ReadAsStreamAsync().Result;
                sr = new StreamReader(ResponseStream, Encoding.GetEncoding("utf-8"));
                retString = sr.ReadToEnd();

                return new HttpResponseResult
                {
                    Content = retString,
                    StatusCode = response.StatusCode,
                    Headers = response.Headers
                        .Concat(response.Content.Headers)
                        .ToDictionary(h => h.Key, h => string.Join(";", h.Value))
                };
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.Message);
                throw;
            }
            finally
            {
                response?.Dispose();
                sr?.Close();
                ResponseStream?.Close();
                httpclient?.Dispose();
            }
        }

        public async Task<string> HttpclientCallAsync(string url, HttpContent paramlist, Dictionary<string, string> customHeaders, ProxySetting proxySetting, HttpMethodType httpMethodType)
        {
            HttpClient httpclient = null;
            Stream ResponseStream = null;
            StreamReader sr = null;
            HttpResponseMessage response = null;
            try
            {
                httpclient = HttpClientSettings(customHeaders, proxySetting, url);
                CompressedContent content = null;
                if (paramlist != null)
                {
                    content = new CompressedContent(paramlist, CompressionType.GZip);
                }
                string retString = string.Empty;

                switch (httpMethodType)
                {
                    case HttpMethodType.GET:
                        response = await httpclient.GetAsync(new Uri(url));
                        break;
                    case HttpMethodType.POST:
                        response = await httpclient.PostAsync(new Uri(url), content);
                        break;
                    case HttpMethodType.PUT:
                        response = await httpclient.PutAsync(new Uri(url), content);
                        break;
                    case HttpMethodType.DELETE:
                        response = await httpclient.DeleteAsync(new Uri(url));
                        break;
                    default:
                        throw new NotSupportedException("This type is not supported!");
                }
                response.EnsureSuccessStatusCode();

                ResponseStream = await response.Content.ReadAsStreamAsync();
                sr = new StreamReader(ResponseStream, Encoding.GetEncoding("utf-8"));
                retString = sr.ReadToEnd();

                return retString;
            }
            catch
            {
                throw;
            }
            finally
            {
                response?.Dispose();
                sr?.Close();
                ResponseStream?.Close();
                httpclient?.Dispose();
            }
        }

        public static HttpResult<T> Post<T>(string url, object param = null, HttpMethodType httpMethodType = HttpMethodType.POST, Dictionary<string, string> customHeaders = null)
        {
            JKHttpUtil httpUtil = new JKHttpUtil();
            HttpContent paramList = null;
            if (param != null)
            {
                if (param.GetType() == typeof(string))
                {
                    paramList = new StringContent(param.ToString(), Encoding.UTF8, "application/x-www-form-urlencoded");
                }
                else
                {
                    paramList = new StringContent(JsonConvert.SerializeObject(param), Encoding.UTF8, "application/json");
                }
            }
            HttpResponseResult result = httpUtil.HttpclientCall(url, paramList, customHeaders, null, httpMethodType);
            T data = default;

            if (!string.IsNullOrWhiteSpace(result.Content))
            {
                data = typeof(T) == typeof(string)
                    ? (T)(object)result.Content
                    : JsonConvert.DeserializeObject<T>(result.Content);
            }

            return new HttpResult<T>
            {
                Data = data,
                Headers = result.Headers
            };
        }

        public static HttpResult<T> Get<T>(string url, object param = null, HttpMethodType httpMethodType = HttpMethodType.GET, Dictionary<string, string> customHeaders = null)
        {
            return Post<T>(url, param, httpMethodType, customHeaders);
        }

        // 新增：文件上传
        public static HttpResult<T> UploadFile<T>(
            string url,
            string filePath,
            string formFieldName = "file",
            Dictionary<string, string> additionalFormFields = null,
            Dictionary<string, string> customHeaders = null)
        {
            if (string.IsNullOrWhiteSpace(filePath) || !File.Exists(filePath))
            {
                throw new FileNotFoundException("文件不存在", filePath);
            }

            JKHttpUtil httpUtil = new JKHttpUtil();

            var multipart = new MultipartFormDataContent();

            // 文件内容
            var fileStream = new FileStream(filePath, FileMode.Open, FileAccess.Read, FileShare.Read);
            var fileContent = new StreamContent(fileStream);
            fileContent.Headers.ContentType = MediaTypeHeaderValue.Parse("application/zip");
            multipart.Add(fileContent, formFieldName, Path.GetFileName(filePath));

            // 额外字段
            if (additionalFormFields != null)
            {
                foreach (var kv in additionalFormFields)
                {
                    if (kv.Value != null)
                    {
                        multipart.Add(new StringContent(kv.Value, Encoding.UTF8), kv.Key);
                    }
                }
            }

            // 关闭压缩（multipart 不应再包装 GZip）
            var resp = httpUtil.HttpclientCall(url, multipart, customHeaders, null, HttpMethodType.POST, false);

            T data = default;
            if (!string.IsNullOrWhiteSpace(resp.Content))
            {
                data = typeof(T) == typeof(string)
                    ? (T)(object)resp.Content
                    : JsonConvert.DeserializeObject<T>(resp.Content);
            }

            // 释放文件流
            fileStream.Dispose();

            return new HttpResult<T>
            {
                Data = data,
                Headers = resp.Headers
            };
        }
    }
}
